<?php

declare(strict_types=1);

namespace app\service\user\login;

use app\model\UserAuth;
use app\model\UserProfile;
use app\model\User;
use InvalidArgumentException;
use think\facade\Db;

class Platform implements LoginInterface
{
    public function login(array $credentials): array
    {
        $ticket = trim((string) ($credentials['ticket'] ?? ''));
        if ($ticket === '') {
            throw new InvalidArgumentException('ticket 不能为空');
        }

        $nickname = trim((string) ($credentials['nickname'] ?? '扫码体验用户'));
        $avatar = trim((string) ($credentials['avatar'] ?? ''));
        $openId = trim((string) ($credentials['openid'] ?? ''));
        $identifier = $openId !== '' ? $openId : $this->normalizeIdentifier($ticket);

        /** @var UserAuth|null $userAuth */
        $userAuth = UserAuth::where('identity_type', 'platform_mock')
            ->where('identifier', $identifier)
            ->find();

        if ($userAuth && $userAuth->user) {
            $this->refreshExistingUser($userAuth, $nickname, $avatar);
            return [
                'status' => 'success',
                'user' => $userAuth->user()->with(['profile'])->find(),
                'msg' => '平台模拟登录成功',
            ];
        }

        if (!$userAuth) {
            $userAuth = new UserAuth([
                'identity_type' => 'platform_mock',
                'identifier' => $identifier,
                'credential' => hash('sha1', $ticket),
                'status' => 1,
                'metadata' => [
                    'nickname' => $nickname,
                    'avatar' => $avatar,
                    'ticket' => $ticket,
                ],
            ]);
        } else {
            $metadata = is_array($userAuth->metadata) ? $userAuth->metadata : [];
            if ($nickname !== '') {
                $metadata['nickname'] = $nickname;
            }
            if ($avatar !== '') {
                $metadata['avatar'] = $avatar;
            }
            if ($ticket !== '') {
                $metadata['ticket'] = $ticket;
            }
            $userAuth->metadata = $metadata;
        }

        return [
            'status' => 'need_bind_phone',
            'user' => $userAuth,
            'msg' => '请先绑定手机号后继续',
        ];
    }

    private function normalizeIdentifier(string $ticket): string
    {
        return 'platform_mock_' . substr(sha1($ticket), 0, 32);
    }

    private function refreshExistingUser(UserAuth $userAuth, string $nickname, string $avatar): void
    {
        Db::transaction(function () use ($userAuth, $nickname, $avatar) {
            $user = $userAuth->user()->find();
            if (!$user instanceof User) {
                return;
            }

            $now = date('Y-m-d H:i:s');
            $user->last_login_time = $now;
            if ($user->register_channel === null) {
                $user->register_channel = 'platform_mock';
            }
            $user->save();

            $profile = $user->profile;
            if (!$profile) {
                $user->profile()->save(new UserProfile([
                    'nickname' => $nickname !== '' ? $nickname : '扫码体验用户',
                    'avatar' => $avatar,
                ]));
            } else {
                $updates = [];
                if ($nickname !== '' && $profile->nickname !== $nickname) {
                    $updates['nickname'] = $nickname;
                }
                if ($avatar !== '' && $profile->avatar !== $avatar) {
                    $updates['avatar'] = $avatar;
                }
                if ($updates !== []) {
                    $profile->save($updates);
                }
            }

            $metadata = is_array($userAuth->metadata) ? $userAuth->metadata : [];
            if ($nickname !== '') {
                $metadata['nickname'] = $nickname;
            }
            if ($avatar !== '') {
                $metadata['avatar'] = $avatar;
            }
            $userAuth->metadata = $metadata;
            $userAuth->save();
        });
    }

    public function getIdentifier(): string
    {
        return 'platform';
    }
}
